package com.xxgc.cloud.error.center.aop;

import cn.hutool.core.util.ArrayUtil;
import com.xxgc.cloud.error.center.BaseException;
import com.xxgc.cloud.error.center.StackTraceElementSize;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.net.*;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.List;

/**
 * @program: SpringCloudStudy
 * @description:
 * @author: Mr.abel(ShiJiaYi)
 * @create: 2022-11-23 17:29
 **/
@Slf4j
@Aspect
@Component
public class AddExceptionPath {

    @Pointcut("execution (* *..*.controller.*.*(..))")
    public void errorPoint(){}

    @AfterThrowing(value = "errorPoint()",throwing = "ex")
    public void beforeAdvice(JoinPoint joinPoint, BaseException ex) {
        //获取方法上的自定义注解
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();
        StackTraceElementSize stes = method.getAnnotation(StackTraceElementSize.class);
        //判断有没有配置自定义注解
        int num = stes != null ? stes.stackTraceElementSize() : 1;
        //移除数组其他，只保留第一位
        StackTraceElement[] resize = ArrayUtil.resize(ex.getStackTrace(), num);
        ex.setStackTrace(resize);
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        //log.error("全路径 IP        "+request.getRemoteAddr());
        ex.setPrivateIpAddress(AddExceptionPath.getIpAddress());
        //给返回异常添加请求路径
        ex.setPath(request.getRequestURI().toString());
        //给返回路径添加错误方法
        ex.setMethodName(signature.getDeclaringTypeName()+"."+signature.getName());
    }

    /**
     * 获取当前服务器ip地址
     * @return
     * @throws SocketException
     */
    private static List<String> getIpAddress(){
        try {
            List<String> list = new LinkedList<>();
            Enumeration enumeration = NetworkInterface.getNetworkInterfaces();
            while (enumeration.hasMoreElements()) {
                NetworkInterface network = (NetworkInterface) enumeration.nextElement();
                if (network.isVirtual() || !network.isUp()) {
                    continue;
                } else {
                    Enumeration addresses = network.getInetAddresses();
                    while (addresses.hasMoreElements()) {
                        InetAddress address = (InetAddress) addresses.nextElement();
                        if (address != null && (address instanceof Inet4Address || address instanceof Inet6Address)) {
                            list.add(address.getHostAddress());
                        }
                    }
                }
            }
            return list;
        }catch (SocketException se){
            //获取ip地址失败
            return null;
        }
    }
}
